﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using MakeIT.MiraPark.Negocios;
using System.Text.RegularExpressions;

namespace MiraPark
{
    public partial class FormCadastroSaida : Form
    {
        CabineVO cabineVO = CabineVO.CreateCabineVO();
        UsuarioVO usuarioVO = UsuarioVO.CreateUsuarioVO();
        
        private CorVO corVO = null;
        private TipoVeiculoVO tipoVeiculoVO = null;
        private MarcaVO marcaVO = null;
        private ModeloVO modeloVO = null;
        private MovimentacaoVO movimentacaoVO = null;
        private List<MovimentoVO> listMovimentoVOs = null;

        public FormCadastroSaida()
        {
            InitializeComponent();
        }

        private void buttonFecharJanela_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FormCadastroSaida_Load(object sender, EventArgs e)
        {
            cabineVO = ModelBO.getCabine(int.Parse(ModelBO.getParametro(ParametroVO.parametros.IdCabine)));
            this.Text = ".:: Cabine - " + cabineVO.cabine + " ::. Saída de Veículo Placa: " + movimentacaoVO.placa + " Ticket: " + movimentacaoVO.ticket;

            this.labelTolerancia.Text = ModelBO.getParametro("Tolerancia");

            this.labelPlaca.Text = movimentacaoVO.placa;
            this.labelTicket.Text = movimentacaoVO.ticket.ToString();
            this.labelTipoCobranca.Text = movimentacaoVO.especie;

            this.labelMensalista.Text = "";
            this.labelConvenio.Text = "";
            this.labelDiaria.Text = "";
            this.labelFeriado.Text = "";
            this.labelOutraData.Text = "";
            this.labelFormaPagamento.Text = "";

            FeriadoVO feriadoVO = ModelBO.getFeriado(movimentacaoVO.entrada);
            if (feriadoVO != null)
            {
                this.labelFeriado.Text = feriadoVO.feriado;
                this.labelFeriado.Tag = feriadoVO;
            }

            OutraDataVO outraDataVO = ModelBO.getOutraData(movimentacaoVO.entrada);
            if (outraDataVO != null)
            {
                this.labelOutraData.Text = outraDataVO.motivo;
                this.labelOutraData.Tag = outraDataVO;
            }
            if (movimentacaoVO.especie.Equals(MovimentacaoVO.Especie.Avulso))
            {
                List<ConvenioVO> convenioVOs = ModelBO.getConvenios(true);
                for (int i = 0; i < 7; i++)
                {
                    Control myButton = this.groupBoxConvenio.Controls["buttonConvenio" + (i + 1)];
                    if (i + 1 <= convenioVOs.Count)
                    {
                        ConvenioVO myConvenio = convenioVOs[i];
                        myButton.Text = myConvenio.clienteVO.nome.ToUpper().Trim();
                        myButton.Tag = myConvenio;
                        myButton.Enabled = true;
                    }
                    else
                    {
                        myButton.Text = "";
                        myButton.Tag = null;
                        myButton.Enabled = false;
                    }
                }
                this.buttonMaisConvenios.Enabled = (convenioVOs.Count > 7);
                this.buttonDiariaEspecial.Enabled = true;
                this.checkBoxPendencia.Enabled = true;
            }
            if (movimentacaoVO.especie.Equals(MovimentacaoVO.Especie.Mensal))
            {
                MensalistaVO mensalistaVO = ModelBO.getMensalistaByPlaca(movimentacaoVO.placa);
                this.labelMensalista.Text = mensalistaVO.clienteVO.nome;
                this.labelMensalista.Tag = mensalistaVO;
            }
            if (movimentacaoVO.especie.Equals(MovimentacaoVO.Especie.Diaria))
            {
            }
            if (movimentacaoVO.especie.Equals(MovimentacaoVO.Especie.DiariaEspecial))
            {
            }
            if (movimentacaoVO.especie.Equals(MovimentacaoVO.Especie.Convenio))
            {
            }
            // convenio e diaria não estão setados ainda.

            List<FormaPagamentoVO> listFormaPagamentoVOs = ModelBO.getFormaPagamentos();
            for (int i = 0; i < 2; i++)
            {
                Control myButton = this.groupBoxFormaPagamento.Controls["buttonFormaPagamento" + (i + 1)];
                if (i + 1 <= listFormaPagamentoVOs.Count)
                {
                    FormaPagamentoVO myFormaPagamento = listFormaPagamentoVOs[i];
                    myButton.Text = myFormaPagamento.formaPagamento.ToUpper().Trim();
                    myButton.Tag = myFormaPagamento;
                    myButton.Enabled = true;

                    if (i == 0)
                    {
                        this.labelFormaPagamento.Text = myButton.Text;
                        this.labelFormaPagamento.Tag = myButton.Tag;
                    }

                }
                else
                {
                    myButton.Text = "";
                    myButton.Tag = null;
                    myButton.Enabled = false;
                }
            }
            this.buttonMaisFormasPagamento.Enabled = (listFormaPagamentoVOs.Count > 2);

            calcular(false);
        }
        
        public void setMovimentacaoVO(MovimentacaoVO movimentacaoVO, CorVO corVO, TipoVeiculoVO tipoVeiculoVO, MarcaVO marcaVO, ModeloVO modeloVO, UsuarioVO usuarioVO)
        {
            this.usuarioVO = usuarioVO;
            this.movimentacaoVO = movimentacaoVO;

            this.movimentacaoVO.saida = DateTime.Now;

            this.textBoxTimeEntrada.Text = this.movimentacaoVO.entrada.ToLongTimeString();
            this.monthCalendarEntrada.TodayDate = this.movimentacaoVO.entrada;
            this.textBoxTimeSaida.Text = this.movimentacaoVO.saida.ToLongTimeString();
            this.monthCalendarSaida.TodayDate = this.movimentacaoVO.saida;

            if (corVO!=null) this.corVO = corVO;
            if (tipoVeiculoVO!=null) this.tipoVeiculoVO = tipoVeiculoVO;
            if (marcaVO!=null) this.marcaVO = marcaVO;
            if (modeloVO != null) this.modeloVO = modeloVO;
        }

        private void buttonConvenio1_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;

            // se for o mesmo modelo, limpar a seleção (on/off)
            if (labelConvenio.Text.Equals(btn.Text))
            {
                this.labelConvenio.Text = "";
                this.labelConvenio.Tag = null;
                this.labelTipoCobranca.Text = MovimentacaoVO.Especie.Avulso;
                movimentacaoVO.especie = MovimentacaoVO.Especie.Avulso;
            }
            else
            {
                this.labelConvenio.Text = btn.Text;
                this.labelConvenio.Tag = btn.Tag;
                this.labelTipoCobranca.Text = MovimentacaoVO.Especie.Convenio;
                movimentacaoVO.especie = MovimentacaoVO.Especie.Convenio;
            }
            this.labelDiaria.Text = "";
            this.textBoxTicket.Text = "";
            this.buttonFinalizar.Enabled = false;
        }
        private void buttonMaisConvenios_Click(object sender, EventArgs e)
        {
            FormMaisSelect formx = new FormMaisSelect();
            formx.MaisConvenios(new System.EventHandler(this.buttonConvenio1_Click));
            formx.ShowDialog(this);
        }

        private void buttonFormaPagamento1_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;

            // se for a mesma forma de pagamento, limpar a seleção (on/off)
            if (labelFormaPagamento.Text.Equals(btn.Text))
            {
                this.labelFormaPagamento.Text = "";
                this.labelFormaPagamento.Tag = null;
            }
            else
            {
                this.labelFormaPagamento.Text = btn.Text;
                this.labelFormaPagamento.Tag = btn.Tag;
            }
        }
        private void buttonMaisFormasPagamento_Click(object sender, EventArgs e)
        {
            FormMaisSelect formx = new FormMaisSelect();
            formx.MaisFormasPagamento(new System.EventHandler(this.buttonFormaPagamento1_Click));
            formx.ShowDialog(this);
        }

        private void buttonDiariaEspecial_Click(object sender, EventArgs e)
        {
            if (this.labelDiaria.Text.Equals(((Button)sender).Text))
            {
                this.labelDiaria.Text = "";
                movimentacaoVO.especie = MovimentacaoVO.Especie.Avulso;
            }
            else
            {
                this.labelDiaria.Text = ((Button)sender).Text;
                movimentacaoVO.especie = MovimentacaoVO.Especie.DiariaEspecial;
            }
            this.labelTipoCobranca.Text = MovimentacaoVO.Especie.Avulso;
            this.labelConvenio.Text = "";
            this.labelConvenio.Tag = null;
            this.textBoxTicket.Text = "";
            this.buttonFinalizar.Enabled = false;
        }

        private void buttonFinalizar_Click(object sender, EventArgs e)
        {
            calcular(true);
        }
        private void buttonCalcular_Click(object sender, EventArgs e)
        {
            calcular(false);
        }

        private void calcular( bool finaliza)
        {
            DateTime dtEntRef = movimentacaoVO.entrada;
            DateTime dtSaiRef = movimentacaoVO.saida;
            //dtEntRef = dtEntRef.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo)));
            //dtSaiRef = dtSaiRef.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo)));
            double toleranciaPeriodo = double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo));
            string tipoCobranca = labelTipoCobranca.Text;
            string idTabelaAnt = "";
            int periodo = 0;
            decimal valor = 0.0M;
            decimal valorTotal = 0.0M;
            
            this.textBoxTicket.Text = "";
            listMovimentoVOs = new List<MovimentoVO>();
            List<RecebimentoVO> listRecebimentosVOs = new List<RecebimentoVO>();

            //ler outras datas
            List<OutraDataVO> listOutraDataVOs = ModelBO.getOutraDatas(movimentacaoVO.entrada, this.monthCalendarSaida.TodayDate);
            
            //ler feriados
            List<FeriadoVO> listFeriadoVOs = ModelBO.getFeriados(movimentacaoVO.entrada, this.monthCalendarSaida.TodayDate);

            //ler tabela avulso
            List<TabelaAvulsoVO> listTabelaAvulsoVOs = ModelBO.getTabelaAvulsos(movimentacaoVO.entrada, this.monthCalendarSaida.TodayDate);
            foreach (TabelaAvulsoVO tabelaAvulsoVO in listTabelaAvulsoVOs)
            {
                ModelBO.getTabelaAvulsoXPeriodos(tabelaAvulsoVO);
                tabelaAvulsoVO.horarioVO = ModelBO.getHorario(tabelaAvulsoVO.idHorario);
            }

            //ler tabela de convenio
            ConvenioVO convenioVO = null;
            TabelaConvenioVO tabelaConvenioVO = null;
            if (labelTipoCobranca.Text.Equals(MovimentacaoVO.Especie.Convenio))
            {
                convenioVO = (ConvenioVO)labelConvenio.Tag;
                tabelaConvenioVO = ModelBO.getTabelaConvenio(convenioVO.idTabelaConvenio);
                ModelBO.getTabelaConvenioXPeriodos(tabelaConvenioVO);
                tabelaConvenioVO.horarioVO = ModelBO.getHorario(tabelaConvenioVO.idHorario);
            }

            //ler tabela mensalista
            MensalistaVO mensalistaVO = null;
            TabelaMensalVO tabelaMensalVO = null;
            List<MensalistaXFranquiaVO> listMensalistaXFranquiaVOs = new List<MensalistaXFranquiaVO>();
            if (labelTipoCobranca.Text.Equals(MovimentacaoVO.Especie.Mensal))
            {
                mensalistaVO = (MensalistaVO)labelMensalista.Tag;
                tabelaMensalVO = ModelBO.getTabelaMensal(mensalistaVO.idTabelaMensal);
                tabelaMensalVO.horarioVO = ModelBO.getHorario(tabelaMensalVO.idHorario);
                listMensalistaXFranquiaVOs = ModelBO.getMensalistaXFranquia(mensalistaVO.idMensalista, movimentacaoVO.entrada, movimentacaoVO.saida);

                //procurar recebimentos em aberto
                listRecebimentosVOs =  ModelBO.getRecebimentos(null, null, mensalistaVO.idMensalista, null, true, false, new DateTime(1,1,1), DateTime.Today, null, null);
                foreach(RecebimentoVO recebimentoVO in listRecebimentosVOs) {
                    MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                    movimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                    movimentoVO.especie = MovimentacaoVO.Especie.Mensal;
                    movimentoVO.idTabelaAvulso = -1;
                    movimentoVO.idTabelaConvenio = -1;
                    movimentoVO.idTabelaConvenioP = -1;
                    movimentoVO.idTabelaMensal = tabelaMensalVO.idTabelaMensal;
                    movimentoVO.periodo = recebimentoVO.recebimento;
                    movimentoVO.valor = recebimentoVO.valor;
                    movimentoVO.valorConvenio = 0.0M;
                    movimentoVO.valorConvenioExtra = 0.0M;
                    listMovimentoVOs.Add(movimentoVO);

                    valorTotal += recebimentoVO.valor;
                }
            }

            if (movimentacaoVO.entrada.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.Tolerancia))) < movimentacaoVO.saida)
            {
                while (dtEntRef < dtSaiRef)
                {

                    // é outra data
                    bool outraData = false;
                    OutraDataVO outraDataVO = null;
                    foreach (OutraDataVO odVO in listOutraDataVOs)
                    {
                        if (dtEntRef >= odVO.outraDataInicial.Add(odVO.horaInicial) &&
                            dtEntRef <= odVO.outraDataFinal.Add(odVO.horaFinal))
                        {
                            outraDataVO = odVO;
                            outraData = true;
                            break;
                        }
                    }
                    // é feriado
                    bool feriado = false;
                    FeriadoVO feriadoVO = null;
                    foreach (FeriadoVO fVO in listFeriadoVOs)
                    {
                        if (dtEntRef >= fVO.idFeriado.Add(fVO.horaInicial) &&
                            dtEntRef <= fVO.idFeriado.Add(fVO.horaFinal))
                        {
                            feriadoVO = fVO;
                            feriado = true;
                            break;
                        }
                    }
                    // qual dia da semana?
                    bool dom = dtEntRef.DayOfWeek == DayOfWeek.Sunday;
                    bool seg = dtEntRef.DayOfWeek == DayOfWeek.Monday;
                    bool ter = dtEntRef.DayOfWeek == DayOfWeek.Tuesday;
                    bool qua = dtEntRef.DayOfWeek == DayOfWeek.Wednesday;
                    bool qui = dtEntRef.DayOfWeek == DayOfWeek.Thursday;
                    bool sex = dtEntRef.DayOfWeek == DayOfWeek.Friday;
                    bool sab = dtEntRef.DayOfWeek == DayOfWeek.Saturday;

                    // é diaria
                    bool diae = this.labelDiaria.Text.Equals(this.buttonDiariaEspecial.Text);

                    if (tipoCobranca.Equals(MovimentacaoVO.Especie.Avulso))
                    {
                        bool encontrou = false;
                        foreach (TabelaAvulsoVO tpVO in listTabelaAvulsoVOs)
                        {
                            //verificar se permite o dia
                            if ((outraData && tpVO.outrasDatas) || (feriado && tpVO.feriados) || (seg && tpVO.segunda) ||
                                (ter && tpVO.terca) || (qua && tpVO.quarta) || (qui && tpVO.quinta) || (sex && tpVO.sexta) ||
                                (sab && tpVO.sabado) || (dom && tpVO.domingo))
                            {
                                //verificar se permite o horário
                                if (outraData || feriado ||
                                   (diae && checkIntervalo(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicialDiaria, tpVO.horarioVO.horaFinalDiaria)) ||
                                   (!diae && (seg || ter || qua || qui || sex) && checkIntervalo(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicial, tpVO.horarioVO.horaFinal)) ||
                                   (!diae && sab && checkIntervalo(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicialSab, tpVO.horarioVO.horaFinalSab)) ||
                                   (!diae && dom && checkIntervalo(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicialDom, tpVO.horarioVO.horaFinalDom)))
                                {
                                    if (!idTabelaAnt.Equals(tpVO.idTabelaAvulso.ToString() + "A"))
                                    {
                                        periodo = 0;
                                        valorTotal += valor;
                                        valor = 0.0m;
                                    }

                                    if (diae || tpVO.tabelaAvulsoPVOs.Count == 0)
                                    {
                                        valor += (diae ? tpVO.diariaEspecial : tpVO.diaria);
                                        //if (tpVO.valorMaximo > 0)
                                        //    valor = Math.Min(valor, tpVO.valorMaximo);

                                        idTabelaAnt = tpVO.idTabelaAvulso.ToString() + "A";
                                        tipoCobranca = this.labelTipoCobranca.Text;
                                        encontrou = true;

                                        MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                                        movimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                                        movimentoVO.especie = (diae ? MovimentacaoVO.Especie.DiariaEspecial : MovimentacaoVO.Especie.Diaria);
                                        movimentoVO.idTabelaAvulso = tpVO.idTabelaAvulso;
                                        movimentoVO.idTabelaConvenio = -1;
                                        movimentoVO.idTabelaConvenioP = -1;
                                        movimentoVO.idTabelaMensal = -1;
                                        movimentoVO.periodo = dtEntRef.ToShortDateString()+" (" + tpVO.tabelaAvulso.Trim() + ")";
                                        movimentoVO.valor = (diae ? tpVO.diariaEspecial : tpVO.diaria);
                                        movimentoVO.valorConvenio = 0.0M;
                                        movimentoVO.valorConvenioExtra = 0.0M;
                                        listMovimentoVOs.Add(movimentoVO);

                                        if (outraData) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, outraDataVO.horaInicial, outraDataVO.horaFinal));
                                        else if (feriado) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, feriadoVO.horaInicial, feriadoVO.horaFinal));
                                        else if (sab) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicialSab, tpVO.horarioVO.horaFinalSab));
                                        else if (dom) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicialDom, tpVO.horarioVO.horaFinalDom));
                                        else if (seg || ter || qua || qui || sex) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tpVO.horarioVO.horaInicial, tpVO.horarioVO.horaFinal));

                                        break;
                                    }
                                    else
                                    { // por periodo
                                        if (tpVO.tabelaAvulsoPVOs.Count > 0)
                                        {
                                            if (periodo >= tpVO.tabelaAvulsoPVOs.Count)
                                                periodo = tpVO.tabelaAvulsoPVOs.Count - 1;

                                            decimal valorAnt = valor;
                                            if (tpVO.tabelaAvulsoPVOs[periodo].acumula)
                                                valor += tpVO.tabelaAvulsoPVOs[periodo].valor;
                                            else
                                                valor = tpVO.tabelaAvulsoPVOs[periodo].valor;

                                            if (tpVO.diaria > 0)
                                                valor = Math.Min(valor, tpVO.diaria);

                                            if (valor != valorAnt)
                                            {
                                                MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                                                movimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                                                movimentoVO.especie = MovimentacaoVO.Especie.Avulso;
                                                movimentoVO.idTabelaAvulso = tpVO.idTabelaAvulso;
                                                movimentoVO.idTabelaConvenio = -1;
                                                movimentoVO.idTabelaConvenioP = -1;
                                                movimentoVO.idTabelaMensal = -1;
                                                movimentoVO.periodo = dtEntRef.ToString("dd/MM") + " " + tpVO.tabelaAvulsoPVOs[periodo].minutos + "min. (" + tpVO.tabelaAvulso.Trim() + ")";
                                                movimentoVO.valor = valor - valorAnt; //tpVO.tabelaAvulsoPVOs[periodo].valor;
                                                movimentoVO.valorConvenio = 0.0M;
                                                movimentoVO.valorConvenioExtra = 0.0M;
                                                listMovimentoVOs.Add(movimentoVO);
                                            }
                                            dtEntRef = dtEntRef.AddMinutes(tpVO.tabelaAvulsoPVOs[periodo].minutos);

                                            idTabelaAnt = tpVO.idTabelaAvulso.ToString() + "A";
                                            tipoCobranca = this.labelTipoCobranca.Text;
                                            encontrou = true;
                                            periodo++;

                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if (!encontrou)
                        {
                            MessageBox.Show("Não encontrado tabela para " + dtEntRef.ToString(), "Aviso");
                            return;
                        }

                    }
                    else if (tipoCobranca.Equals(MovimentacaoVO.Especie.Convenio))
                    {
                        bool encontrou = false;
                        //verificar se permite o dia
                        if ((outraData && tabelaConvenioVO.outrasDatas) || (feriado && tabelaConvenioVO.feriados) || (seg && tabelaConvenioVO.segunda) ||
                            (ter && tabelaConvenioVO.terca) || (qua && tabelaConvenioVO.quarta) || (qui && tabelaConvenioVO.quinta) || (sex && tabelaConvenioVO.sexta) ||
                            (sab && tabelaConvenioVO.sabado) || (dom && tabelaConvenioVO.domingo))
                        {
                            //verificar se permite o horário
                            if (outraData || feriado ||
                               ((seg || ter || qua || qui || sex) && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicial, tabelaConvenioVO.horarioVO.horaFinal)) ||
                               (sab && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicialSab, tabelaConvenioVO.horarioVO.horaFinalSab)) ||
                               (dom && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicialDom, tabelaConvenioVO.horarioVO.horaFinalDom)))
                            {
                                if (!idTabelaAnt.Equals(tabelaConvenioVO.idTabelaConvenio.ToString() + "C"))
                                {
                                    periodo = 0;
                                    valorTotal += valor;
                                    valor = 0.0m;
                                }
                                if (tabelaConvenioVO.tabelaConvenioPVOs.Count > 0)
                                {
                                    if (periodo >= tabelaConvenioVO.tabelaConvenioPVOs.Count)
                                    {
                                        periodo = tabelaConvenioVO.tabelaConvenioPVOs.Count - 1;
                                        if (!tabelaConvenioVO.tabelaConvenioPVOs[periodo].acumula)
                                        {
                                            periodo = 0;
                                            valorTotal += valor;
                                            valor = 0.0m;
                                        }
                                    }

                                    if (tabelaConvenioVO.tabelaConvenioPVOs[periodo].acumula)
                                        valor += tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;
                                    else
                                    {
                                        valor = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;

                                        if (listMovimentoVOs.Count > 0 && periodo!=0)
                                        {
                                            ((MovimentoVO)listMovimentoVOs[listMovimentoVOs.Count - 1]).valor = 0;
                                            ((MovimentoVO)listMovimentoVOs[listMovimentoVOs.Count - 1]).valorConvenio = 0;
                                        }
                                    }

                                    if (tabelaConvenioVO.valorMaximo > 0)
                                        valor = Math.Min(valor, tabelaConvenioVO.valorMaximo);

                                    dtEntRef = dtEntRef.AddMinutes(tabelaConvenioVO.tabelaConvenioPVOs[periodo].minutos);
                                    MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                                    movimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                                    movimentoVO.especie = MovimentacaoVO.Especie.Convenio;
                                    movimentoVO.idTabelaAvulso = -1;
                                    movimentoVO.idTabelaConvenio = tabelaConvenioVO.idTabelaConvenio;
                                    movimentoVO.idTabelaConvenioP = tabelaConvenioVO.tabelaConvenioPVOs[periodo].idTabelaConvenioP;
                                    movimentoVO.idTabelaMensal = -1;
                                    movimentoVO.periodo = tabelaConvenioVO.tabelaConvenioPVOs[periodo].minutos + "min. (" + tabelaConvenioVO.tabelaConvenio.Trim() + ")";
                                    movimentoVO.valor = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;
                                    movimentoVO.valorConvenio = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorConvenio;
                                    movimentoVO.valorConvenioExtra = 0.0M;
                                    listMovimentoVOs.Add(movimentoVO);

                                    movimentacaoVO.idConvenio = convenioVO.idConvenio;

                                    idTabelaAnt = tabelaConvenioVO.idTabelaConvenio.ToString() + "C";
                                    encontrou = true;
                                    periodo++;


                                }
                            }
                        }
                        if (!encontrou)
                            tipoCobranca = MovimentacaoVO.Especie.Avulso;

                    }
                    else if (tipoCobranca.Equals(MovimentacaoVO.Especie.Mensal))
                    {
                        bool encontrou = false;
                        //verificar se existe franquia
                        if (listMensalistaXFranquiaVOs.Find(f=> dtEntRef >=f.dataIni && dtEntRef<=f.dataFim)!=null)
                        {                        
                            //verificar se permite o horário
                            if (((seg || ter || qua || qui || sex) && checkIntervalo(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicial, tabelaMensalVO.horarioVO.horaFinal)) ||
                               (sab && checkIntervalo(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicialSab, tabelaMensalVO.horarioVO.horaFinalSab)) ||
                               (dom && checkIntervalo(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicialDom, tabelaMensalVO.horarioVO.horaFinalDom)))
                            {
                                if (!idTabelaAnt.Equals(tabelaMensalVO.idTabelaMensal.ToString() + "M"))
                                {
                                    periodo = 0;
                                    valorTotal += valor;
                                    valor = 0.0m;
                                }
                                if (outraData) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, outraDataVO.horaInicial, outraDataVO.horaFinal));
                                else if (feriado) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, feriadoVO.horaInicial, feriadoVO.horaFinal));
                                else if (sab) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicialSab, tabelaMensalVO.horarioVO.horaFinalSab));
                                else if (dom) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicialDom, tabelaMensalVO.horarioVO.horaFinalDom));
                                else if (seg || ter || qua || qui || sex) dtEntRef = dtEntRef.AddTicks(addTicks(dtEntRef.TimeOfDay, tabelaMensalVO.horarioVO.horaInicial, tabelaMensalVO.horarioVO.horaFinal));
                                valor = 0; //tabelaMensalVO.valor;
                                idTabelaAnt = tabelaMensalVO.idTabelaMensal.ToString() + "M";
                                encontrou = true;

                                MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                                movimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                                movimentoVO.especie = MovimentacaoVO.Especie.Mensal;
                                movimentoVO.idTabelaAvulso = -1;
                                movimentoVO.idTabelaConvenio = -1;
                                movimentoVO.idTabelaConvenioP = -1;
                                movimentoVO.idTabelaMensal = tabelaMensalVO.idTabelaMensal;
                                movimentoVO.periodo = "(" + tabelaMensalVO.tabelaMensal.Trim() + ")";
                                movimentoVO.valor = 0.0M; //tabelaMensalVO.valor;
                                movimentoVO.valorConvenio = 0.0M;
                                movimentoVO.valorConvenioExtra = 0.0M;
                                listMovimentoVOs.Add(movimentoVO);

                            }
                        }
                        if (!encontrou)
                            tipoCobranca = MovimentacaoVO.Especie.Avulso;
                    }

                    //verifica tolerancia para proximo periodo
                    if (dtEntRef.AddMinutes(toleranciaPeriodo) >= dtSaiRef)
                        break;
                }
            }
            valorTotal += valor;
            valor = 0.0m;
            StringBuilder mensagem = new StringBuilder();
//            for (int i = 0; i < 2; i++)
//            {
                mensagem.Append(Ticket.getHeader());
                mensagem.AppendLine("<ce>RECIBO " + movimentacaoVO.saida.ToString("dddd dd/MM/yyyy HH:mm:ss") + "</ce>");
                mensagem.AppendLine("------------------------------------------------");
//                mensagem.AppendLine("Via " + (i == 0 ? "Estacionamento" : "Cliente"));
                mensagem.AppendLine("");
                mensagem.AppendLine("Seq.: " + movimentacaoVO.ticket.ToString().PadLeft(4, '0'));
                mensagem.AppendLine((marcaVO != null ? marcaVO.marca + " " : "") + (modeloVO != null ? modeloVO.modelo + " " : "") + (corVO != null ? corVO.nome : ""));
                mensagem.AppendLine("<b>Placa : " + movimentacaoVO.placa + "</b>");
                mensagem.AppendLine("Entrada : " + movimentacaoVO.entrada.ToShortDateString() + " Hora : " + movimentacaoVO.entrada.ToString());
                TimeSpan estadia = movimentacaoVO.saida - movimentacaoVO.entrada;
                mensagem.AppendLine("Tempo estacionado : " + Math.Floor(estadia.TotalHours).ToString() + "h" + estadia.Minutes.ToString().PadLeft(2, '0') + "m" + estadia.Seconds.ToString().PadLeft(2, '0') + "s");
                mensagem.AppendLine("");
                foreach (MovimentoVO movimentoVO in listMovimentoVOs)
                    mensagem.AppendLine(movimentoVO.especie + " Per.: " + movimentoVO.periodo + " " + movimentoVO.valor.ToString("#,#.00"));
                mensagem.AppendLine("------------------------------------------------");
                mensagem.AppendLine("<ad>Total estadia : " + valorTotal.ToString("#,#.00") + "</ad>");
                mensagem.AppendLine("Pagos da seguinte forma");

                if (this.checkBoxPendencia.Checked)
                    if ((decimal)this.checkBoxPendencia.Tag == valorTotal)
                        mensagem.AppendLine("<ad>** A pagar **</ad>");
                    else
                    {
                        mensagem.AppendLine("<ad>" + (this.labelFormaPagamento.Tag != null ? ((FormaPagamentoVO)this.labelFormaPagamento.Tag).formaPagamento : "Dinheiro") + " : " + (valorTotal-(decimal)this.checkBoxPendencia.Tag).ToString("#,#.00") + "</ad>");
                        mensagem.AppendLine("<ad>** A pagar:" + ((decimal)this.checkBoxPendencia.Tag).ToString("#,#.00") + "</ad>");
                    }
                else
                    mensagem.AppendLine("<ad>" + (this.labelFormaPagamento.Tag != null ? ((FormaPagamentoVO)this.labelFormaPagamento.Tag).formaPagamento : "Dinheiro") + " : " + valorTotal.ToString("#,#.00") + "</ad>");

                mensagem.Append(Ticket.getFooter(this.checkBoxDeclaracao.Checked,cabineVO, usuarioVO));
//            }
            this.textBoxTicket.Text = Ticket.cutText(mensagem.ToString());
            this.buttonFinalizar.Enabled = true;

            if (finaliza)
            {
                if (this.monthCalendarSaida.TodayDate.Date <= DateTime.Parse(ModelBO.getParametro(ParametroVO.parametros.FechamentoDiario)).Date)
                {
                    MessageBox.Show("Fechamento executado para a data atual!\nOperação bloqueada!");
                    return;
                }

                bool imprimeTicket = true;
                if (this.labelTipoCobranca.Text.Equals(MovimentacaoVO.Especie.Mensal)){
                    //DialogResult dr = MessageBox.Show(this, "Deseja imprimir o Ticket de saída para o Mensalista?", "Confirmação", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    //if (dr.ToString().Equals("Yes"))
                    //    imprimeTicket=true;
                    //else
                        imprimeTicket=false;
                }


                while (imprimeTicket)
                {
                    if (!Ticket.checkPrint() || !Ticket.printTicket(mensagem.ToString()))
                    {
                        DialogResult dr = MessageBox.Show(this, "Tentar novamente?", "Confirmação", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if (dr.ToString().Equals("Yes"))
                        {
                            continue;
                        }
                        dr = MessageBox.Show(this, "Deseja efetivar a entrada sem a emissão do ticket?", "Confirmação", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                        if (dr.ToString().Equals("Yes"))
                        {
                            FormMessage formx = new FormMessage();
                            formx.setText(Ticket.cutText(mensagem.ToString()));
                            formx.ShowDialog(this);
                            break;
                        }
                        else
                        {
                            return;
                        }
                    }
                    else
                    {
                        break;
                    }

                }

                //Gravar saida
                movimentacaoVO.idCabineS = cabineVO.idCabine;
                movimentacaoVO.valor = valorTotal;

                ModelBO.setMovimentacao(movimentacaoVO);
                ModelBO.newMovimentos(listMovimentoVOs);

                foreach (RecebimentoVO recebimentoVO in listRecebimentosVOs)
                {
                    recebimentoVO.dtPagamento = DateTime.Now;
                    recebimentoVO.idMovimentacao = movimentacaoVO.idMovimentacao;
                    recebimentoVO.valorRec = recebimentoVO.valor;
                    if (this.labelFormaPagamento.Tag != null)
                        recebimentoVO.formaPagamentoVO.idFormaPagamento = ((FormaPagamentoVO)this.labelFormaPagamento.Tag).idFormaPagamento;
                    else
                        recebimentoVO.formaPagamentoVO.idFormaPagamento = -1;

                    valorTotal -= recebimentoVO.valor;
                }
                ModelBO.setRecebimentos(listRecebimentosVOs);

                if (valorTotal > 0)
                {
                    RecebimentoVO recebimentoVO2 = RecebimentoVO.CreateRecebimentoVO();
                    recebimentoVO2.recebimento = "Saida estacionamento";
                    recebimentoVO2.dtVencimento = DateTime.Today;
                    recebimentoVO2.dtPagamento = DateTime.Now;
                    recebimentoVO2.idMovimentacao = movimentacaoVO.idMovimentacao;
                    recebimentoVO2.valor = valorTotal;

                    if (this.checkBoxPendencia.Checked)
                        recebimentoVO2.valorRec = valorTotal - (decimal)this.checkBoxPendencia.Tag;
                    else
                        recebimentoVO2.valorRec = valorTotal;

                    if (this.labelFormaPagamento.Tag != null)
                        recebimentoVO2.formaPagamentoVO.idFormaPagamento = ((FormaPagamentoVO)this.labelFormaPagamento.Tag).idFormaPagamento;
                    else
                        recebimentoVO2.formaPagamentoVO.idFormaPagamento = -1;

                    if (mensalistaVO != null)
                        recebimentoVO2.idMensalista = mensalistaVO.idMensalista;
                    else
                        recebimentoVO2.idMensalista = -1;
                    if (convenioVO != null)
                        recebimentoVO2.idConvenio = convenioVO.idConvenio;
                    else
                        recebimentoVO2.idConvenio = -1;

                    if (recebimentoVO2.valorRec!=0)
                        ModelBO.newRecebimento(recebimentoVO2);

                    if (this.checkBoxPendencia.Checked)
                    {
                        movimentacaoVO.especie = MovimentacaoVO.Especie.Pendencia;
                        movimentacaoVO.valor = (decimal)this.checkBoxPendencia.Tag * -1;

                        PendenciaVO pendenciaVO = PendenciaVO.CreatePendenciaVO();
                        pendenciaVO.formaPagamentoVO.idFormaPagamento = -1;
                        pendenciaVO.idOperador = -1;
                        pendenciaVO.pendencia = "Estadia "+movimentacaoVO.entrada.ToShortDateString()+" Ticket "+movimentacaoVO.ticket;
                        pendenciaVO.placa = movimentacaoVO.placa;
                        pendenciaVO.valor = (decimal)this.checkBoxPendencia.Tag;

                        ModelBO.newMovimentacao(movimentacaoVO);
                        ModelBO.newPendencia(pendenciaVO);

                    }
                }

                this.Close();
            }
        }

        public bool checkIntervalo(TimeSpan saida, TimeSpan ini, TimeSpan fin)
        {
            if (ini.Ticks <= fin.Ticks)
            {
                return (saida.Ticks >= ini.Ticks && saida.Ticks <= fin.Ticks);
            }
            TimeSpan time24h = new TimeSpan(24, 0, 0);
            return (saida.Ticks >= ini.Ticks && saida.Ticks <= time24h.Ticks) || (saida.Ticks <= fin.Ticks);
        }
        public long addTicks(TimeSpan saida, TimeSpan ini, TimeSpan fin)
        {
            TimeSpan time24h = new TimeSpan(24, 0, 0);
            TimeSpan second = new TimeSpan(0, 0, 1);
            if (ini.Ticks >= fin.Ticks)
            {
                if (saida.Ticks >= ini.Ticks)
                {
                    return time24h.Ticks - saida.Ticks + fin.Ticks + second.Ticks;
                }
                else
                {
                    return fin.Ticks - saida.Ticks + second.Ticks;
                }
            }
            return fin.Ticks - saida.Ticks + second.Ticks;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<MovimentacaoVO> lm = ModelBO.getMovimentacoes(null, null, ((ConvenioVO)labelConvenio.Tag).idConvenio,null,null,null,null,false,false,null,true,false,false,false,false);

            foreach( MovimentacaoVO m in lm)
            {


//================================================================================================
                DateTime dtEntRef = m.entrada;
                DateTime dtSaiRef = m.saida;
                //dtEntRef = dtEntRef.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo)));
                //dtSaiRef = dtSaiRef.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo)));
                double toleranciaPeriodo = double.Parse(ModelBO.getParametro(ParametroVO.parametros.ToleranciaPeriodo));
                string tipoCobranca = labelTipoCobranca.Text;
                string idTabelaAnt = "";
                int periodo = 0;
                decimal valor = 0.0M;
                decimal valorTotal = 0.0M;

                this.textBoxTicket.Text = "";
                listMovimentoVOs = new List<MovimentoVO>();
                List<RecebimentoVO> listRecebimentosVOs = new List<RecebimentoVO>();

                //ler tabela de convenio
                ConvenioVO convenioVO = null;
                TabelaConvenioVO tabelaConvenioVO = null;
                if (labelTipoCobranca.Text.Equals(MovimentacaoVO.Especie.Convenio))
                {
                    convenioVO = (ConvenioVO)labelConvenio.Tag;
                    tabelaConvenioVO = ModelBO.getTabelaConvenio(convenioVO.idTabelaConvenio);
                    ModelBO.getTabelaConvenioXPeriodos(tabelaConvenioVO);
                    tabelaConvenioVO.horarioVO = ModelBO.getHorario(tabelaConvenioVO.idHorario);
                }

                if (m.entrada.AddMinutes(double.Parse(ModelBO.getParametro(ParametroVO.parametros.Tolerancia))) < m.saida)
                {
                    while (dtEntRef < dtSaiRef)
                    {

                        // qual dia da semana?
                        bool dom = dtEntRef.DayOfWeek == DayOfWeek.Sunday;
                        bool seg = dtEntRef.DayOfWeek == DayOfWeek.Monday;
                        bool ter = dtEntRef.DayOfWeek == DayOfWeek.Tuesday;
                        bool qua = dtEntRef.DayOfWeek == DayOfWeek.Wednesday;
                        bool qui = dtEntRef.DayOfWeek == DayOfWeek.Thursday;
                        bool sex = dtEntRef.DayOfWeek == DayOfWeek.Friday;
                        bool sab = dtEntRef.DayOfWeek == DayOfWeek.Saturday;

                        if (tipoCobranca.Equals(MovimentacaoVO.Especie.Convenio))
                        {
                            bool encontrou = false;
                            //verificar se permite o dia
                            if ((seg && tabelaConvenioVO.segunda) ||
                                (ter && tabelaConvenioVO.terca) || (qua && tabelaConvenioVO.quarta) || (qui && tabelaConvenioVO.quinta) || (sex && tabelaConvenioVO.sexta) ||
                                (sab && tabelaConvenioVO.sabado) || (dom && tabelaConvenioVO.domingo))
                            {
                                //verificar se permite o horário
                                if ((seg || ter || qua || qui || sex) && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicial, tabelaConvenioVO.horarioVO.horaFinal) ||
                                   (sab && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicialSab, tabelaConvenioVO.horarioVO.horaFinalSab)) ||
                                   (dom && checkIntervalo(dtEntRef.TimeOfDay, tabelaConvenioVO.horarioVO.horaInicialDom, tabelaConvenioVO.horarioVO.horaFinalDom)))
                                {
                                    if (!idTabelaAnt.Equals(tabelaConvenioVO.idTabelaConvenio.ToString() + "C"))
                                    {
                                        periodo = 0;
                                        valorTotal += valor;
                                        valor = 0.0m;
                                    }
                                    if (tabelaConvenioVO.tabelaConvenioPVOs.Count > 0)
                                    {
                                        if (periodo >= tabelaConvenioVO.tabelaConvenioPVOs.Count)
                                        {
                                            periodo = tabelaConvenioVO.tabelaConvenioPVOs.Count - 1;
                                            if (!tabelaConvenioVO.tabelaConvenioPVOs[periodo].acumula)
                                            {
                                                periodo = 0;
                                                valorTotal += valor;
                                                valor = 0.0m;
                                            }
                                        }

                                        if (tabelaConvenioVO.tabelaConvenioPVOs[periodo].acumula)
                                            valor += tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;
                                        else
                                        {
                                            valor = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;

                                            if (listMovimentoVOs.Count > 0 && periodo != 0)
                                            {
                                                ((MovimentoVO)listMovimentoVOs[listMovimentoVOs.Count - 1]).valor = 0;
                                                ((MovimentoVO)listMovimentoVOs[listMovimentoVOs.Count - 1]).valorConvenio = 0;
                                            }
                                        }

                                        if (tabelaConvenioVO.valorMaximo > 0)
                                            valor = Math.Min(valor, tabelaConvenioVO.valorMaximo);

                                        dtEntRef = dtEntRef.AddMinutes(tabelaConvenioVO.tabelaConvenioPVOs[periodo].minutos);
                                        MovimentoVO movimentoVO = MovimentoVO.CreateMovimentoVO();
                                        movimentoVO.idMovimentacao = m.idMovimentacao;
                                        movimentoVO.especie = MovimentacaoVO.Especie.Convenio;
                                        movimentoVO.idTabelaAvulso = -1;
                                        movimentoVO.idTabelaConvenio = tabelaConvenioVO.idTabelaConvenio;
                                        movimentoVO.idTabelaConvenioP = tabelaConvenioVO.tabelaConvenioPVOs[periodo].idTabelaConvenioP;
                                        movimentoVO.idTabelaMensal = -1;
                                        movimentoVO.periodo = tabelaConvenioVO.tabelaConvenioPVOs[periodo].minutos + "min. (" + tabelaConvenioVO.tabelaConvenio.Trim() + ")";
                                        movimentoVO.valor = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorCliente;
                                        movimentoVO.valorConvenio = tabelaConvenioVO.tabelaConvenioPVOs[periodo].valorConvenio;
                                        movimentoVO.valorConvenioExtra = 0.0M;
                                        listMovimentoVOs.Add(movimentoVO);

                                        m.idConvenio = convenioVO.idConvenio;

                                        idTabelaAnt = tabelaConvenioVO.idTabelaConvenio.ToString() + "C";
                                        encontrou = true;
                                        periodo++;

                                    }
                                }
                            }
                            if (!encontrou)
                                tipoCobranca = MovimentacaoVO.Especie.Avulso;

                        }

                        //verifica tolerancia para proximo periodo
                        if (dtEntRef.AddMinutes(toleranciaPeriodo) >= dtSaiRef)
                            break;
                    }
                }
                valorTotal += valor;
                valor = 0.0m;


                //Gravar saida
                m.idCabineS = cabineVO.idCabine;
                m.valor = valorTotal;

                ModelBO.setMovimentacao(m);
                ModelBO.delMovimentos(m.movimentoVOs);
                ModelBO.newMovimentos(listMovimentoVOs);

                if (valorTotal > 0)
                {
                    RecebimentoVO recebimentoVO2 = null;
                    List<RecebimentoVO> lr = ModelBO.getRecebimentos(null, m.idMovimentacao,null,null,false,false,null,null,null,null);
                    if (lr != null && lr.Count > 0)
                    {
                        recebimentoVO2 = lr[0];
                    }
                    else
                    {
                        recebimentoVO2 = RecebimentoVO.CreateRecebimentoVO();
                        recebimentoVO2.recebimento = "Saida estacionamento";
                        recebimentoVO2.dtVencimento = DateTime.Today;
                        recebimentoVO2.dtPagamento = DateTime.Now;
                        recebimentoVO2.idMovimentacao = m.idMovimentacao;
                        recebimentoVO2.formaPagamentoVO.idFormaPagamento = 1;
                        recebimentoVO2.idMensalista = -1;
                        recebimentoVO2.idConvenio = convenioVO.idConvenio;
                    }
                    
                    recebimentoVO2.valor = valorTotal;
                    recebimentoVO2.valorRec = valorTotal;

                    ModelBO.newRecebimento(recebimentoVO2);
                }


            }

        
        }

        private void checkBoxPendencia_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxPendencia.Checked)
            {
                FormEditaPendencia formx = new FormEditaPendencia();
                formx.ShowDialog(this);
                this.checkBoxPendencia.Tag = formx.getValor();
                decimal valor = (decimal)this.checkBoxPendencia.Tag;
                if (valor == 0)
                    this.checkBoxPendencia.Checked = false;
                else
                    this.checkBoxPendencia.Text = "Pendência\n" + valor.ToString("C");
            }
            else 
            {
                this.checkBoxPendencia.Tag = null;
                this.checkBoxPendencia.Text = "Pendência";
            }
        }
    }
}
